<template>
  <div>
    <v-progress-linear color="error" v-model="progress" />
    <small> {{ practice.used }} / {{ practice.total }} </small>
    <v-btn style="float: right" @click="resetPractice" class="ma-2" color="indigo" icon="mdi-refresh" />
    <v-btn style="float: right" @click="getWordDetail(null, previousList[previousListFlag].word)" class="ma-2"
      color="indigo" icon="mdi-information" />
    <v-btn style="float: right" ref="practiceSetting" @click="practiceSetting" class="ma-2" color="indigo"
      icon="mdi-cog" />
  </div>
  <span style="margin:0px auto;height: 25px;">
    <v-icon v-if="examResult == '对'" icon="mdi-thumb-up" color="success" />
    <v-icon v-if="examResult == '错'" icon="mdi-thumb-down" color="red" />
  </span>
  <div class="centerDiv">
    <slot name="center"></slot>
  </div>
  <div class="detail_bottom">
    <v-divider></v-divider>
    <br />
    <div style="display: flex;justify-content: space-between;">
      <span v-if="
        previousList != null &&
        previousList.length > 0 &&
        this.previousListFlag > 0
      " style="cursor: pointer" @click="previousRaw">
        <v-icon start icon="mdi-arrow-left"></v-icon>上一个
      </span>
      <span v-else style="cursor: not-allowed;"><v-icon start icon="mdi-arrow-left"></v-icon>上一个</span>
      <strong @click="unknownWord" style="cursor: pointer;font-size: 20px;">不会</strong>
      <span style="cursor: pointer" v-if="practice.used != practice.total" @click="nextRaw(null)">
        下一个<v-icon start icon="mdi-arrow-right"></v-icon>
      </span>
    </div>
    <SimpleKeyboard ref="simpleKeyboardRef" :input="VKeyboardInput" :isVibrate="practiceConfig.isVibrate"
      v-if="practiceConfig.showKeyboard && practiceConfig.showKeyboardSwitch" @onChange="onChange"
      @onKeyPress="onKeyPress" />
  </div>

  <v-snackbar v-model="snackbar" multi-line>
    {{ text }}
  </v-snackbar>

  <word-detail-dialog-view :closeDialogListener="closeDialogListener" v-show="showDetailDialog"
    ref="DetailDialogView" />

  <v-overlay :model-value="overlay" class="align-center justify-center">
    <v-progress-circular color="primary" indeterminate size="64"></v-progress-circular>
  </v-overlay>

  <v-dialog v-model="settingDialog">
    <v-card title="设置">
      <div style="padding: 0px 10px">
        <v-switch color="primary" v-if="practiceConfig.showAutoPlay" v-model="practiceConfig.autoPlay" label="关闭/自动 单词发音" />
        <v-switch color="primary" v-if="practiceConfig.showWordSymbolSwitch" v-model="practiceConfig.wordSymbol" label="关闭/显示 音标" />
        <v-switch color="primary" v-if="practiceConfig.showAutoPlayResponded" v-model="practiceConfig.autoPlayResponded"
          label="选择正确答案后自动单词发音" />
        <v-switch color="primary" v-if="practiceConfig.showAutoPlayVoice" v-model="practiceConfig.autoPlayVoice" label="关闭/自动 阅读单词解释" />
        <v-switch color="primary" v-if="practiceConfig.showAutoCover" v-model="practiceConfig.autoCover" label="关闭/自动 遮住" />
        <v-switch color="primary" v-if="practiceConfig.showKeyboardSwitch" v-model="practiceConfig.showKeyboard" label="关闭/显示 屏幕键盘" />
        <v-switch color="primary" v-if="practiceConfig.showVibrateSwitch" v-model="practiceConfig.isVibrate" label="关闭/开启 振动效果" />
        <v-switch color="primary" v-if="practiceConfig.showTitleSwitch" v-model="practiceConfig.titleSwitch" label="关闭/显示 题目" />
        <v-switch color="primary" v-if="practiceConfig.showTitleExplainSwitch" v-model="practiceConfig.titleExplainSwitch"
          label="隐藏/显示 题目释意" />
        <v-switch color="primary" v-if="practiceConfig.showSymbolSwitch" v-model="practiceConfig.symbolSwitch" label="隐藏显示 音标" />
        <v-switch color="primary" v-if="practiceConfig.showTitleLocalSwitch" v-model="practiceConfig.titleLocalSwitch"
          label="题目显示 原语言/本地语言 解释" />
        <v-switch color="primary" v-if="practiceConfig.showChooseItemSwitch" v-model="practiceConfig.chooseItemSwitch"
          label="选项显示 翻译/原语言解释" />
        <v-switch color="primary" v-if="practiceConfig.showWordChooseSwitch" v-model="practiceConfig.wordChooseSwitch"
          label="选项 关闭/显示 单词" />
        <v-switch color="primary" v-if="practiceConfig.showReplyTypeSwitch" v-model="practiceConfig.replyTypeSwitch" label="回答单词/意思" />
        <v-switch color="primary" v-if="practiceConfig.showReplyWordSwitch" v-model="practiceConfig.replyWordSwitch" label="回答单词" />
        <v-switch color="primary" v-if="practiceConfig.showReplyMeanSwitch" v-model="practiceConfig.replyMeanSwitch" label="回答意思" />
        <v-switch color="primary" v-if="practiceConfig.showQuickKeySwitch" v-model="practiceConfig.quickKeySwitch" label="启用快捷键" />
        <v-switch color="primary" v-if="practiceConfig.showSensorSwitch" v-model="practiceConfig.sensorSwitch" label="启用传感器" />
        <v-switch color="primary" v-if="practiceConfig.showPalmSwitch" v-model="practiceConfig.palmSwitch" label="单手模式" />
        <v-switch color="primary" v-model="practiceConfig.showPic" label="显示图片" />
        <v-btn color="red" @click="deletePracticeConfig">删除配置</v-btn>
      </div>
      <v-card-actions>
        <v-spacer />
        <v-btn color="gray" @click="settingDialog = false" text="确定" />
        <v-btn text="应用并保存" color="primary" @click="savePracticeConfig" />
      </v-card-actions>
    </v-card>
  </v-dialog>

  <v-dialog v-model="finishDialog">
    <v-card title="学习提示">
      <v-card-text> 当前词典已完成复习 </v-card-text>
      <v-card-actions>
        <v-spacer />
        <v-btn text="确认" @click="finishDialog = false" />
      </v-card-actions>
    </v-card>
  </v-dialog>
</template>

<script>
import {
  listeningAndWriting,
  nextRow,
  reset,
  setUserPracticeConfig,
  deleteUserPracticeConfig,
} from "@/api/practice.js";
import { isResourceExist, ttsVoice } from "@/api/voice.js";
import WordDetailDialogView from "../views/practice/WordDetailDialogView.vue";
import SimpleKeyboard from '@/components/SimpleKeyboard.vue';
export default {
  name: "PracticeFrame",
  components: { WordDetailDialogView, SimpleKeyboard },
  props: {
    practiceModel: String,
    setPracticeCallback: Function,
    pushPreviousWord: Function,
    tryPlayWordSymbolVoice: Function,
    clearPracticeConfigCallback: Function,
    quickKeyListener: Function,
    VKeyboardInputListener: Function,
    VKeyboardPressListener: Function,
    getVKeyboardRef: Function,
    autoPalyOnceListener:Function,
    sensorListener: {
      type: Function, default: (data) => { }
    }
  },
  data() {
    return {
      snackbar: false,
      text: "",
      voiceLoading: true,
      myAnswer: null,
      progress: 0,
      bufferValue: 80,
      mute: false,
      showAnswer: false,
      currentWord: { word: "", meanSelf: "", explain: "", wordId: 0 },
      wordTemp: undefined,
      practice: { total: 0, used: 0 },
      blur: true,
      overlay: false,
      examResult: undefined,
      wordAudio: null,
      settingDialog: false,
      practiceConfig: {
        autoPlay: false,
        showAutoPlay: false,
      },
      getVoiceTimeout: null,
      showDetailDialog: false,
      previousList: [],
      previousListFlag: -1,
      finishDialog: false,
      pressedCtrlKey: false,
      executedKeyCode: -1,
      showingWordDetail: false,
      retry: false,
      VKeyboardInput: ''
    };
  },
  created() {
    if (this.getVKeyboardRef != null && this.$refs.simpleKeyboardRef != null) this.getVKeyboardRef(this.$refs.simpleKeyboardRef)
    this.sensorRegister()
  },
  methods: {
    onChange(input) {
      this.VKeyboardInput = input
      if (this.VKeyboardInputListener != null) this.VKeyboardInputListener(input)
    },
    onKeyPress(button) {
      if (this.VKeyboardPressListener != null) this.VKeyboardPressListener(button)
    },
    restoreVKeyboardInput() {
      if (!this.practiceConfig.showKeyboardSwitch || !this.practiceConfig.showKeyboard) return
      if (this.$refs.simpleKeyboardRef != null) this.$refs.simpleKeyboardRef.restoreVKeyboardInput()
    },
    setVKeyboardInput(content) {
      if (!this.practiceConfig.showKeyboardSwitch || !this.practiceConfig.showKeyboard) return
      setTimeout(() => {
        this.$refs.simpleKeyboardRef.setVKeyboardInput(content)
      }, 500);
    },
    setPractice(practice) {
      this.practice = practice;
      this.progress =
        ((this.practice.used * 100) / (this.practice.total * 100)) * 100;
    },
    loadingListeningAndWritingCache() {
      this.overlay = true;
      listeningAndWriting({ bookId: this.$route.params.bookId })
        .then(() => {
          this.nextRaw();
        })
        .finally(() => (this.overlay = false));
    },
    refreshCurrent() {
      if (this.wordTemp == undefined) return;
      this.trans(this.wordTemp);
    },
    nextRaw(rightWordId) {
      this.overlay = true;
      // console.log('nextRaw = ',this.previousList,this.previousListFlag);
      if (
        this.previousListFlag < 100 &&
        this.previousListFlag >= 0 &&
        this.previousListFlag < this.previousList.length - 1
      ) {
        this.previousListFlag += 1;
        this.practice = this.previousList[this.previousListFlag];
        this.setPracticeCallback(this.previousList[this.previousListFlag]);
        this.wordTemp=this.previousList[this.previousListFlag].word
        this.overlay = false;
        this.autoPlayOnce();
        // console.log('previousRaw -> if = ',this.previousList,this.previousListFlag);
        return;
      }
      nextRow({
        bookId: this.$route.params.bookId,
        practiceModel: this.practiceModel,
        wordId: rightWordId,
      })
        .then((resp) => {
          // console.log(resp)
          // this.currentWord=resp.data
          if (resp.data != null) {
            this.wordTemp = resp.data.word;
            // this.trans(resp.data.word)
            this.practice = resp.data;
            this.progress =
              ((this.practice.used * 100) / (this.practice.total * 100)) * 100;
            this.setPracticeCallback(this.practice);
            this.autoPlayOnce();
            if (this.practice.used == this.practice.total)
              this.finishDialog = true;
            else {
              this.previousList.push(resp.data);
              if (this.previousList.length > 100) {
                this.previousList.shift();
              }
              this.previousListFlag = this.previousList.length - 1;
            }
            this.retry = false
            this.examResult = undefined;
            // console.log('previousRaw - > push = ',this.previousList,this.previousListFlag);
            // console.log(this.practice.used*100/(this.practice.total*100)*100+" % ");
          } else {
            this.finishDialog = true;
          }
        })
        .finally(() => (this.overlay = false));
    },
    previousRaw() {
      // this.previousList.pop()
      // console.log('previousRaw = ',this.previousList,this.previousListFlag);
      if (
        this.previousList.length == 0 ||
        this.previousListFlag < 0 ||
        this.previousListFlag - 1 < 0
      )
        return;
      // if(this.previousListFlag==this.previousList.length)this.previousListFlag-=2;else this.previousListFlag-=1
      this.previousListFlag -= 1;
      this.practice = this.previousList[this.previousListFlag];
      this.setPracticeCallback(this.previousList[this.previousListFlag]);
      this.wordTemp=this.previousList[this.previousListFlag].word
      this.autoPlayOnce()
      // console.log('previous = ',this.previousList[this.previousListFlag]);
    },
    unknownWord() {
      this.getWordDetail()
      if (this.practiceConfig.autoPlayResponded) {
        this.autoPlayOnce(true)
        this.reply({ right: false }, null, true)
      } else this.reply({ right: false })
      this.retry = true
    },
    trans() { },
    reply(item, replyCallback, dontPlayErrorAudio) {
      // this.snackbar = true
      // let voiceURL=''
      if (item.right) {
        // this.text = '回答正确'
        this.myAnswer = null;
        this.blur = true;
        this.examResult = "对";
        // voiceURL='/api/file/voice/right.mp3'
        if (!this.practiceConfig.autoPlayResponded) this.playResultAudio(true);
      } else {
        // this.snackbar = true;
        this.text = "回答错误";
        this.examResult = "错";
        if (!dontPlayErrorAudio) this.playResultAudio(false);
        this.retry = true
        // voiceURL='/api/file/voice/wrong.mp3'
      }
      if (replyCallback != null) replyCallback()
      // let audio = new Audio(voiceURL)
      // audio.play()
      if (this.practiceConfig.autoPlayResponded && item.right) {
        this.autoPlayOnce(true, () => {
          this.examResult = undefined
          this.nextRaw(item.retry || this.retry ? null : item.wordId)
        })
      } else if (item.right) this.nextRaw(item.retry || this.retry ? null : item.wordId)
      else setTimeout(() => { this.examResult = undefined; }, 1000);
    },
    getVoiceResource(text, callback) {
      ttsVoice({ text: text }).then((resp) => {
        callback(resp.data);
      });
    },
    resetPractice() {
      this.overlay=true
      reset({
        bookId: this.$route.params.bookId,
        practiceModel: this.practiceModel,
      }).then((resp) => {
        if (resp.data != null) {
          // this.trans(resp.data.word)
          this.practice = resp.data;
          this.progress =
            ((this.practice.used * 100) / (this.practice.total * 100)) * 100;
          this.setPracticeCallback(resp.data);
        }
      }).finally(()=>this.overlay=false);
    },
    practiceSetting() {
      this.settingDialog = true;
    },
    play() {
      // console.log(this.currentWord);
      // this.playSymbol()
      let audio = new Audio(this.currentWord.symbolResource);
      audio.play();
      audio.onended = () => {
        audio = new Audio(this.currentWord.explainResource);
        audio.play();
      };
    },
    autoPlayOnce(play, callback) {
      this.wordAudio = null;
      if (this.practiceConfig.autoPlay || play) {
        if (this.practice == null || this.practice.word == null) return;
        let pronunciation = this.practice.word.pronunciation;
        if (pronunciation == null || pronunciation.length <= 0) return;
        if (pronunciation.length == 1)
          this.wordAudio = new Audio(pronunciation[0].resource);
        else if (pronunciation.length == 2 && pronunciation[1].region == "美")
          this.wordAudio = new Audio(pronunciation[1].resource);
        else this.wordAudio = new Audio(pronunciation[0].resource);
        if (this.wordAudio != null) {
          this.wordAudio.play()
          // console.log('正在播放 = ',this.wordAudio.src);
          isResourceExist(this.wordAudio.src).then(resp => {
            if (resp.status != 200 && callback != null) callback()
          })
          this.wordAudio.onended = () => {
            if (callback != null) callback()
            if(this.autoPalyOnceListener!=null)this.autoPalyOnceListener()
          }
        }
      }
    },
    deletePracticeConfig() {
      //localStorage.removeItem('practiceConfig-choose')
      deleteUserPracticeConfig({
        bookId: this.$route.params.bookId,
        practiceModel: this.practiceModel,
      }).then(() => {
        this.settingDialog = false;
        if (this.clearPracticeConfigCallback != undefined) this.clearPracticeConfigCallback()
      });
    },
    playSymbol() {
      // console.log('this.currentWord.meanSelf.symbolResource',this.currentWord);
      // let audio = new Audio(this.currentWord.symbolResource)
      // audio.play()
    },
    playExplain() { },
    playResultAudio(result) {
      if (!this.practiceConfig.playResultAudio) return
      let audio = null
      if (result) {
        if (!this.practiceConfig.autoPlay || !this.practiceConfig.showAutoPlay) {
          audio = new Audio("/api/file/voice/right.mp3");
        }
      } else audio = new Audio("/api/file/voice/wrong.mp3")
      if (audio != null) {
        audio.play()
        audio.onended = () => { audio = null }
      }
    },
    getRandomInt(min, max) {
      min = Math.ceil(min);
      max = Math.floor(max);
      return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值，含最小值
    },
    getWordDetail(wordId, wordData) {
      if (this.showingWordDetail) return
      this.showDetailDialog = true;
      if (wordData != null) {
        setTimeout(() => {
          this.$refs.DetailDialogView.toggle(true, null, wordData);
          this.showingWordDetail = true
        }, 100);
        return
      }
      setTimeout(() => {
        this.$refs.DetailDialogView.toggle(true, {
          wordId: wordId != null ? wordId : this.practice.word.wordId,
          bookId: this.$route.params.bookId,
        }, this.wordTemp);
        this.showingWordDetail = true
      }, 100);
    },
    loadingPracticeConfig() {
      let config = localStorage.getItem("practiceConfig");
      if (config == null || config == "") {
        config = { autoPlay: false, autoCover: false, showPic: false };
      }
      this.practiceConfig = config;
      localStorage.setItem(JSON.stringify(config));
    },
    setPracticeConfig(config) {
      this.practiceConfig = config;
      if (config.quickKeySwitch) this.addQuickKey(); else this.removeQuick()
    },
    closeDialogListener() {
      setTimeout(() => {
        this.showDetailDialog = false;
        this.showingWordDetail = false
      }, 100);
    },
    savePracticeConfig() {
      this.settingDialog = false;
      //localStorage.setItem(this.practiceConfig.name,JSON.stringify(this.practiceConfig))
      setUserPracticeConfig({
        bookId: this.$route.params.bookId,
        practiceModel: this.practiceModel,
        configJsonText: JSON.stringify(this.practiceConfig),
      });
      if (this.practiceConfig.quickKeySwitch) this.addQuickKey(); else this.removeQuick()
    },
    addQuickKey() {
      if (this.practiceConfig.quickKeySwitch) {
        document.addEventListener("keydown", this.keyDownEventHandler);
        document.addEventListener("keyup", this.keyUpEventHandler);
      }
    },
    removeQuick() {
      document.removeEventListener("keydown", this.keyDownEventHandler);
      document.removeEventListener("keyup", this.keyUpEventHandler);
    },
    keyUpEventHandler(event) {
      // console.log('松开键, ASCII码:', event.keyCode);
      if (event.keyCode == 17 && this.pressedCtrlKey) {
        this.pressedCtrlKey = false
      }
      if (this.executedKeyCode == event.keyCode) this.executedKeyCode = -1

    },
    keyDownEventHandler(event) {
      // console.log('按下了键, ASCII码:', event.keyCode);
      if (event.keyCode == 27) {
        if (this.showingWordDetail) this.$refs.DetailDialogView.closeDialog();
        this.showingWordDetail = false
        return
      }
      if (event.keyCode != 17 && !this.pressedCtrlKey) return
      if (this.keyEventExecuted) return
      if (this.executedKeyCode == event.keyCode) return
      switch (event.keyCode) {
        case 17:
          this.pressedCtrlKey = true
          break
        case 37:
          if (!this.showingWordDetail) this.previousRaw();
          break;
        case 38:
          this.getWordDetail(null);
          break;
        case 39:
          if (!this.showingWordDetail) this.nextRaw(null);
          break;
        case 27, 40:
          if (this.showingWordDetail) this.$refs.DetailDialogView.closeDialog();
          this.showingWordDetail = false
          break;
        case 190:
          if (!this.showingWordDetail && this.tryPlayWordSymbolVoice != undefined) this.tryPlayWordSymbolVoice()
          break
        case 191:
          if (!this.showingWordDetail) this.unknownWord(null);
          else {
            this.$refs.DetailDialogView.closeDialog();
            this.showingWordDetail = false
          }
          break
      }
      this.executedKeyCode = event.keyCode
      setTimeout(() => {
        if (this.quickKeyListener != undefined && event.keyCode != 17) this.quickKeyListener(event.keyCode)
      }, 0);

    },
    sensorRegister() {
      window.addEventListener('deviceorientation', (event)=>{
        if(this.practiceConfig.showSensorSwitch&&this.practiceConfig.sensorSwitch)this.sensorListener(event)
      }, false);
    }
  },
  beforeUnmount() {
    this.removeQuick()
  },
};
</script>

<style scoped>
.centerDiv {
  width: 100%;
  text-align: center;
  margin: auto;
}

.detail_bottom::after {
  content: "";
  display: block;
}

.detail_bottom span {
  font-size: 18px;
}

.div_blur {
  filter: blur(5px);
}
</style>